package cn.demoncat.util.http.entity;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.demoncat.util.exception.RestRuntimeException;
import cn.demoncat.util.http.HttpUtil;
import cn.demoncat.util.io.CloseUtil;
import okhttp3.Call;
import okhttp3.Response;

/**
 * OkHttp 异步请求回调
 * 
 * @author 延晓磊
 *
 * @since 2019年10月14日
 */
public abstract class HttpCallback implements okhttp3.Callback{

	private static final Logger LOG = LoggerFactory.getLogger(HttpCallback.class);
	
	// 请求信息
	private HttpRequest request;
	
	/**
	 * 默认实现
	 */
	public static HttpCallback DEFAULT = new HttpCallback() {

		@Override
		public void onComplete(HttpResponse response) {
			// 不处理响应结果
		}
	};
	
	/**
	 * 读取响应
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月14日
	 */
	public abstract void onComplete(HttpResponse response);
	
	/**
	 * 请求失败
	 * 
	 * @param call	请求回调
	 * @param e		异步：连接出错、超时、关闭
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年10月14日
	 *
	 */
	@Override
	public void onFailure(Call call, IOException e) {
		// 取消请求
		if (!call.isCanceled()) {
			call.cancel();
		}
		throw error(e);
	}

	/**
	 * 收到响应
	 * 
	 * @param call
	 * @param rep
	 * @throws IOException
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年10月14日
	 *
	 */
	@Override
	public void onResponse(Call call, Response rep) {
		HttpResponse response;
		try {
			// 封装响应
			response = HttpUtil.getResponse(call, rep);
		} catch (IOException e) {
			// 响应失败
			throw error(e);
		}finally {
			// 关闭响应
			CloseUtil.close(rep);
		}
		// 读取响应
		onComplete(response);
	}
	
	/**
	 * 绑定请求信息
	 * 
	 * @param request
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月16日
	 */
	public HttpCallback addRequest(HttpRequest request) {
		this.request = request;
		return this;
	}
	
	/**
	 * 获取请求信息
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月16日
	 */
	public HttpRequest getRequest() {
		return request;
	}
	
	/**
	 * 异常处理
	 * 
	 * @author 延晓磊
	 * @return 
	 *
	 * @since 2020年6月16日
	 */
	private RestRuntimeException error(IOException e) {
		RestRuntimeException ex = RestRuntimeException.httpUrlError(request.getUrl(), e);
		LOG.error("HTTP异步请求失败", ex);
		return ex;
	}
}
